package jp.co.kayo.gae.takidashibot.service;

import java.net.URL;
import java.util.List;
import java.util.logging.Level;

import org.slim3.datastore.Datastore;

import jp.co.kayo.gae.takidashibot.meta.TakidasiMeta;
import jp.co.kayo.gae.takidashibot.meta.TweetInfoMeta;
import jp.co.kayo.gae.takidashibot.model.Takidasi;
import jp.co.kayo.gae.takidashibot.model.TweetInfo;
import jp.co.kayo.gae.takidashibot.utils.TwitterClient;
import jp.co.kayo.gae.takidashibot.utils.Utils;
import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.TwitterException;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;

import com.sun.syndication.feed.module.georss.GeoRSSModule;
import com.sun.syndication.feed.module.georss.GeoRSSUtils;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;


public class RssCheck extends TwitterSerivce{
    
    public void getTakidasiInfo(TwitterClient twitter, String point, String url, String s_url, String hashtag){
        log.log(Level.INFO, point+"の取得処理をします");
        Transaction tx = null;
        SyndFeed feed = null;
        try {
            SyndFeedInput input = new SyndFeedInput();
            feed = input.build(new XmlReader(new URL(url)));
            
            TakidasiMeta tm = TakidasiMeta.get();
            List<SyndEntry> entries = feed.getEntries();
            for (SyndEntry entry : entries){
                GeoRSSModule geo = GeoRSSUtils.getGeoRSS(entry);
                double lat = geo.getPosition().getLatitude();
                double lon = geo.getPosition().getLongitude();
                String uri = entry.getUri();
                
                Takidasi t = Datastore.query(tm).filter(tm.id.equal(uri)).asSingle();
                if (t == null) {
                    // 新規作成
                    String addr = Utils.getAddress(lat, lon);
                    
                    t = new Takidasi();
                    Key wk = KeyFactory.createKey(Takidasi.class.getSimpleName(), uri);
                    t.setKey(wk);
                    t.setName(entry.getTitle());
                    t.setCreatedAt(entry.getPublishedDate().getTime());
                    SyndContent content = entry.getDescription();
                    if(content!=null){
                        t.setDescription(content.getValue());
                    }
                    t.setId(uri);
                    t.setLat(lat);
                    t.setLng(lon);
                    t.setTag(point);
                    t.setAddr(addr);

                    tx = Datastore.beginTransaction();
                    Datastore.put(t);
                    tx.commit();
                    tx = null;
                    
                    StringBuilder buf = new StringBuilder();
                    
                    StringBuilder urlstr = new StringBuilder();
                    //urlstr.append("http://maps.google.com/maps?q=").append(lat).append(",").append(lon).append("+(").append(URLEncoder.encode(entry.getTitle(), "UTF-8")).append(")");
                    urlstr.append("http://takidasibot.appspot.com/takidasibot/item.html?id=").append(t.getId());
                    String shorter = Utils.urlShorter(urlstr.toString());
                    String addurl = s_url;
                    if(shorter!=null){
                        addurl = shorter;
                    }
                    
                    int fixlength = (140-(addurl+" #takidashi "+hashtag).length());
                    
                    if(addr!=null){
                        buf.append(addr);
                    }
                    else{
                        buf.append(point);
                    }
                    buf.append("に炊き出しが追加されました。");
                    buf.append(t.getName());
                    if(entry.getDescription()!=null){
                        Utils.addDescription(buf, entry.getDescription().getValue(), fixlength);
                    }
                    StatusUpdate state = new StatusUpdate(buf.toString() + " "+addurl+" #takidashi "+hashtag);
                    Status ret = twitter.updateState(state);
                    if(ret!=null){
                        /*
                        TweetInfo tweetinf = new TweetInfo();
                        wk = KeyFactory.createKey(TweetInfo.class.getSimpleName(), ret.getId());
                        tweetinf.setKey(wk);
                        tweetinf.setStatusid(ret.getId());
                        tweetinf.setId(t.getId());
                        tweetinf.setCreatedAt(ret.getCreatedAt().getTime());

                        tx = Datastore.beginTransaction();
                        Datastore.put(tweetinf);
                        tx.commit();
                        tx = null;*/
                    }
                }
                else{
                    if(
                        (t.getCreatedAt() != entry.getPublishedDate().getTime() )
                        || (entry.getUpdatedDate()!= null && t.getCreatedAt() != entry.getUpdatedDate().getTime()))
                    {
                        // 更新処理
                        String addr = Utils.getAddress(lat, lon);
                        
                        t.setName(entry.getTitle());
                        if(entry.getUpdatedDate()!=null){
                            t.setCreatedAt(entry.getUpdatedDate().getTime());
                        }
                        else{
                            t.setCreatedAt(entry.getPublishedDate().getTime());
                        }
                        SyndContent content = entry.getDescription();
                        if(content!=null){
                            t.setDescription(content.getValue());
                        }
                        else{
                            t.setDescription("");
                        }
                        t.setLat(lat);
                        t.setLng(lon);
                        t.setTag(point);
                        t.setAddr(addr);
                        
                        tx = Datastore.beginTransaction();
                        Datastore.put(t);
                        tx.commit();
                        tx = null;
                        
                        StringBuilder buf = new StringBuilder();
                        
                        StringBuilder urlstr = new StringBuilder();
                        //urlstr.append("http://maps.google.com/maps?q=").append(lat).append(",").append(lon).append("+(").append(URLEncoder.encode(entry.getTitle(), "UTF-8")).append(")");
                        urlstr.append("http://takidasibot.appspot.com/takidasibot/item.html?id=").append(t.getId());
                        
                        String shorter = Utils.urlShorter(urlstr.toString());
                        String addurl = s_url;
                        if(shorter!=null){
                            addurl = shorter;
                        }
                        
                        int fixlength = (140-(addurl+" #takidashi "+hashtag).length());
                        
                        if(addr!=null){
                            buf.append(addr);
                        }
                        else{
                            buf.append(point);
                        }
                        buf.append("の炊き出しが更新されました。");
                        buf.append(t.getName());
                        if(entry.getDescription()!=null){
                            Utils.addDescription(buf, entry.getDescription().getValue(), fixlength);
                        }
                        StatusUpdate state = new StatusUpdate(buf.toString() + " "+addurl+" #takidashi "+hashtag);
                        Status ret = twitter.updateState(state);
                        if(ret!=null){
                            /*
                            TweetInfo tweetinf = new TweetInfo();
                            Key wk = KeyFactory.createKey(TweetInfo.class.getSimpleName(), ret.getId());
                            tweetinf.setKey(wk);
                            tweetinf.setStatusid(ret.getId());
                            tweetinf.setId(uri);
                            tweetinf.setCreatedAt(ret.getCreatedAt().getTime());
                            
                            tx = Datastore.beginTransaction();
                            Datastore.put(tweetinf);
                            tx.commit();
                            tx = null;*/
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.log(Level.WARNING, "getRSS", e);
        }
        finally{
            if (tx!= null && tx.isActive()){
                tx.rollback();
            }
            if(feed!=null){
                cleanRSS(twitter, point, feed, hashtag);
            }
        }
    }
    
    public void cleanRSS(TwitterClient twitter, String point, SyndFeed feed, String hashtag){
        log.log(Level.INFO, point+"のクリーン処理をします");
        Transaction tx = null;
        try {
            //お掃除処理、Feedにない、Pointデータは削除する
            TakidasiMeta tm = TakidasiMeta.get();
            TweetInfoMeta ttm  = TweetInfoMeta.get();
            List<Takidasi> list = Datastore.query(tm).filter(tm.tag.equal(point)).asList();
            for(Takidasi t : list){
                List<SyndEntry> feeds = feed.getEntries();
                boolean found = false;
                for (SyndEntry ent : feeds){
                    String uri = ent.getUri();
                    if(uri.equals(t.getId())){
                        found = true;
                    }
                }
                if(!found){
                    //削除されたおそれ、消します
                    String title = t.getName();
                    String uri = t.getId();
                    tx = Datastore.beginTransaction();
                    Datastore.delete(t.getKey());
                    tx.commit();
                    tx = null;
                    log.log(Level.INFO, "次のエントリを削除しました"+title);
                }
            }
        } catch (Exception e) {
            log.log(Level.WARNING, "cleanRSS", e);
        }
        finally{
            if (tx!=null && tx.isActive()){
                tx.rollback();
            }
        }
    }
}
